using System;
using System.Collections.Generic;
using System.Text;
using gudusoft.gsqlparser;
using gudusoft.gsqlparser.Units;

namespace iteratesqlparsetree
{
    class iteratesqlparsetree
    {
        static void Main(string[] args)
        {
            TGSqlParser sqlparser = new TGSqlParser(TDbVendor.DbVOracle);
            sqlparser.SqlText.Text = "select f1,fx(p1,t1.p2),sum(t1.x) from t1 where t1.a=10.2 and c='k' and b in (2,4,5) or h in (select f1t2 from t2) having max(x) > 6 ";
            int i = sqlparser.Parse();
            if (i == 0)
            {
                #region using visitor to get function from any parse tree node
                TLzVisitorFindFunction v = new TLzVisitorFindFunction(sqlparser.SqlStatements[0].Fields);
                v.convert();

                //TLzVisitorFindFunction v2 = new TLzVisitorFindFunction((sqlparser.SqlStatements[0] as TSelectSqlStatement).HavingClause);
                //v2.convert();

                #endregion
            }
            else
            {
                Console.WriteLine(sqlparser.ErrorMessages);
            }
        }
    }

    // Illustrate how to create own visitor that descend from TLzVisitorAbs to visitor the parse tree
    // the parse tree can be any type that descend from TLz_node such as TCustomSqlStatement, TLzCustomExpression

    class TLzVisitorFindFunction : TLzVisitorAbs
    {

        TLz_Node parsetree; //parse tree can be any parse tree node descend from TLz_node such as TCustomSqlStatement, TLzCustomExpression


        public TLzVisitorFindFunction(TLz_Node parsetree)
        {
            this.parsetree = parsetree;
        }


        public void convert()
        {
            //simple call Iterate to visit parse tree
            parsetree.Iterate(this);
        }

        //Execute will be called when tree node of type TSourceToken is visited
        //PreExecute will be called just before tree node of any type descend from TLz_node is visited.
        //PostExecute will be called just after tree node of any type descend from TLz_node is visited.

        //Process tree nodes (type of TSourceToken) of the parsetree in Execute method 
        public override void Execute(TLzVisitedAbs pVisited)
        {
            base.Execute(pVisited);
            if (pVisited is TSourceToken)
            {
            }
        }

        //Process tree nodes ( all other type except TSourceToken) of the parsetree in PreExecute/PostExecute method 
        public override void PreExecute(TLzVisitedAbs pVisited)
        {
            if (pVisited is TLz_FuncCall)
            {
                TLz_FuncCall fn = pVisited as TLz_FuncCall;
                Console.WriteLine(fn.AsText + "function name: " + fn.FunctionName);
                for (int k = 0; k < fn.args.Count(); k++)
                {
                    Console.WriteLine(new string(' ', 2) + (fn.args[k] as TLzCustomExpression).AsText);
                }
            }
        }

        public override void PostExecute(TLzVisitedAbs pVisited)
        {
        }

    }

}
